import { useEffect, useRef, useState } from 'react';
import { AnswerRequest, getAnswer, getModelList, PictureQuesionList } from './apis';
import uploadFile from '@/utils/upload';
import { Message } from '@alicloudfe/components';
import dayjs from 'dayjs';
import AtomIntl from '@/utils/intl';

export interface IModel {
  charactersSupport: boolean;
  docSupport: boolean;
  id: string;
  name: string;
  pictureSupport: boolean;
  version: string;
  customModelName: string;
  icon: string;
}

export interface IChatItem {
  type: 'answer' | 'question' | 'loading' | 'answerLoading' | 'canceled';
  modelId: number | string;
  modelName?: string;
  version: string;
  customModelName?: string;
  time: string;
  content: string;
  image?: string;
  icon?: string;
}


// 一条 history 就是一次对话，方便后续进行转换
export interface IHistory {
  bot?: string;
  user: string;
  image?: string;
}

export const FORMAT_DATE_TIME = 'YYYY/MM/DD HH:mm:ss';

interface IProps {
  /**
   * 1-获取全部
   * 2-仅获取当前用户设置了apikey的
   */
  resultType: 1 | 2;
  /**
   * 1:用户
   * 2:组织
   */
  targetType: 1 | 2;
  // 用户/组织id （targetType为2时必传）
  targetId?: string;
  onLoadHaveSetModels?: (list: IModel[]) => void;
  onBeforeSend?: (newChatList: IChatItem[], newChatHistory: IHistory[]) => void;
  onSteamUpdate?: (newChatList: IChatItem[], newChatHistory: IHistory[]) => void;
}

export function useAIAssistant(props: IProps) {
  const {
    targetType,
    targetId,
    resultType,
    onLoadHaveSetModels = () => {},
    onBeforeSend = () => {},
    onSteamUpdate = () => {},
  } = props;
  const [haveSetModelList, setHaveSetModelList] = useState<IModel[]>([]);
  const getUserHaveSetModelList = () => {
    getModelList({
      resultType,
      targetType,
      targetId,
    }).then((res) => {
      const {
        data = [],
      } = res;
      const result: IModel[] = [];
      data.forEach((item: any) => {
        const {
          versionList,
        } = item;
        versionList.forEach((versionObj: {
          version: string;
          customModelName: string;
        }) => {
          const temp = {
            ...item,
            version: versionObj.version,
            customModelName: versionObj.customModelName,
          };
          delete temp.versionList;
          result.push(temp);
        });
      });
      setHaveSetModelList(result);
      onLoadHaveSetModels(result);
    });
  };
  useEffect(() => {
    getUserHaveSetModelList();
  }, []);
  const hasApiKey = !!haveSetModelList.length;

  const [currentModel, setCurrentModel] = useState<IModel>();
  const changeCurrentModel = (modelInfo: IModel) => {
    setCurrentModel(modelInfo);
  };

  const [selectedFile, setSelectedFile] = useState<{
    fileObj: File;
    type: 'img' | 'file';
    ossAddr?: string;
  }>(null);
  const selectedFileRef = useRef<any>();
  useEffect(() => {
    selectedFileRef.current = selectedFile;
  }, [selectedFile]);

  const [uploading, setUploading] = useState(false);
  const uploadFileToOSS = async (file: File) => {
    const parts = file.name.split('.');
    parts.pop();
    try {
      setUploading(true);
      const res = await uploadFile({
        file,
        name: parts.join('.'),
      }) as {
        name: string;
        url: string;
      };
      setUploading(false);
      setSelectedFile({
        ...selectedFileRef.current,
        ossAddr: res.url,
      });
    } catch (err) {
      setUploading(false);
    }
  };

  const [userQuestion, setUserQuestion] = useState('');
  const clearCurrentUserInput = () => {
    setUserQuestion('');
    setSelectedFile(null);
  };

  const [isAsking, setIsAsking] = useState(false);


  const contentAreaRef = useRef<HTMLDivElement>();
  const scrollToChatContentBottom = () => {
    if (!contentAreaRef.current) {
      return;
    }

    setTimeout(() => {
      contentAreaRef.current.scrollTop = contentAreaRef.current.scrollHeight;
    }, 50);
  };

  const [previewingImg, setPreviewingImg] = useState('');
  const openImgPreview = (imgSrc: string) => {
    setPreviewingImg(imgSrc);
  };
  const hideImgPreview = () => {
    setPreviewingImg('');
  };

  const [chatList, setChatList] = useState<IChatItem[]>([]);
  const chatListRef = useRef(chatList);

  const [chatHistory, setChatHistory] = useState<IHistory[]>([]);
  const chatHistoryRef = useRef<IHistory[]>(chatHistory);

  const currentRequest = useRef<any>();
  const sendQuestion = () => {
    const params: AnswerRequest = {
      modelId: currentModel.id,
      version: currentModel.version,
      targetType,
      targetId,
    };

    if (currentModel.pictureSupport || currentModel.docSupport) {
      const pictureQuesionList: PictureQuesionList[] = [];
      chatHistory.forEach((aHistory) => {
        const user: PictureQuesionList = {
          text: aHistory.user,
          role: 'user',
          image: '',
        };
        pictureQuesionList.push(user);
        if (aHistory.bot) {
          const bot: PictureQuesionList = {
            text: aHistory.bot,
            role: 'assistant',
            image: '',
          };
          pictureQuesionList.push(bot);
        }
      });
      pictureQuesionList.push({
        image: selectedFile?.ossAddr || '',
        text: userQuestion,
        role: 'user',
      });
      params.pictureQuesionList = pictureQuesionList;
    } else if (currentModel.charactersSupport) {
      params.prompt = userQuestion;
      params.history = chatHistory as any;
    } else {
      Message.notice(AtomIntl.get('AI_useAI_当前模型不支持提问'));
      return;
    }

    const newQuestionItem: IChatItem = {
      modelId: currentModel.id,
      modelName: currentModel.name,
      version: currentModel.version,
      type: 'question',
      time: dayjs().format(FORMAT_DATE_TIME),
      content: userQuestion,
      image: selectedFile?.ossAddr,
    };
    const aHistory: IHistory = {
      user: userQuestion,
      bot: '',
      image: selectedFile?.ossAddr,
    };
    // chatHistory.push(aHistory);
    const newChatHistory = [...chatHistory];

    const list = [...chatList];
    list.push(newQuestionItem);
    const newAnswerItem: IChatItem = {
      modelId: currentModel.id,
      modelName: currentModel.name,
      version: currentModel.version,
      icon: currentModel.icon,
      type: 'loading',
      time: dayjs().format(FORMAT_DATE_TIME),
      content: '',
    };

    const newChatList = [
      ...list,
      newAnswerItem,
    ];
    clearCurrentUserInput();
    scrollToChatContentBottom();
    setIsAsking(true);

    onBeforeSend(newChatList, newChatHistory);
    const {
      source,
      request,
    } = getAnswer(params, (resp) => {
      const stopped = resp?.output?.finish_reason === 'stop';
      if (stopped) {
        setIsAsking(false);
      }
      newAnswerItem.type = stopped ? 'answer' : 'answerLoading';
      newAnswerItem.content = resp?.output?.text;
      aHistory.bot = newAnswerItem.content;
      const temp = chatHistoryRef.current.filter((i) => i != aHistory);
      temp.push(aHistory);
      const newChatListOnResp = [
        ...list,
        newAnswerItem,
      ];
      const newChatHistoryOnResp = [...temp];
      onSteamUpdate(newChatListOnResp, newChatHistoryOnResp);
      scrollToChatContentBottom();
    });
    request.then(() => {
      setIsAsking(false);
    }).catch(() => {
      setIsAsking(false);
    });
    currentRequest.current = source;
  };

  const disableSendButton = isAsking || uploading || !currentModel || !userQuestion.trim();

  const onInputAreaKeyUp = (event: KeyboardEvent) => {
    if (event.key === 'Enter') {
      if (!disableSendButton) {
        sendQuestion();
      }
      event.preventDefault();
      event.stopPropagation();
      return false;
    }
  };


  return {
    haveSetModelList,
    currentModel,
    changeCurrentModel,
    hasApiKey,

    selectedFile,
    setSelectedFile,
    uploading,
    uploadFileToOSS,

    userQuestion,
    setUserQuestion,
    clearCurrentUserInput,

    isAsking,
    setIsAsking,

    contentAreaRef,
    scrollToChatContentBottom,

    previewingImg,
    openImgPreview,
    hideImgPreview,

    chatList,
    setChatList,
    chatListRef,

    chatHistory,
    setChatHistory,
    chatHistoryRef,

    currentRequest,
    sendQuestion,

    disableSendButton,

    onInputAreaKeyUp,
  };
}

